﻿using System.Collections.Generic;
using System.Windows.Forms;
using MentalAlchemy.Molecules.MachineLearning;

namespace MentalAlchemy.Compounds.MachineLearning
{
	public partial class NeuralNetProperties : UserControl
	{
		#region - Properties. -

		/// <summary>
		/// Obtains user-defined neural network properties.
		/// </summary>
		public Molecules.MachineLearning.NeuralNetProperties NeuralProperties
		{
			get
			{
				var nodes = new List<int>();
				var acts = new List<ActivationFunction>();

				List<NeuralLayerProperties> layers = LayerProperties;
				foreach (NeuralLayerProperties layer in layers)
				{
					if (layer.LayerCheckBox.Checked)
					{
						nodes.Add(layer.LayerSize);
						acts.Add(layer.ActivationFunction);
					}
				}
				var res = new Molecules.MachineLearning.NeuralNetProperties();
				res.actFunctions = acts.ToArray();
				res.nodesNumber = nodes.ToArray();
				res.UseBias = UseBiasCheck.Checked;
				return res;
			}
		}

		/// <summary>
		/// Input layer.
		/// </summary>
		public NeuralLayerProperties InputLayer
		{
			get
			{
				var layers = LayerProperties;
				return layers.Count > 0 ? layers[0] : null;
			}
		}

		/// <summary>
		/// Output layer.
		/// </summary>
		public NeuralLayerProperties OutputLayer
		{
			get
			{
				var layers = LayerProperties;
				return layers.Count > 0 ? layers[layers.Count - 1] : null;
			}
		}

		/// <summary>
		/// List of properties for each layer.
		/// </summary>
		public List<NeuralLayerProperties> LayerProperties
		{
			get
			{
				var res = new List<NeuralLayerProperties>();
				foreach (object ctrl in groupBox1.Controls)
				{
					if (ctrl is NeuralLayerProperties)
					{
						res.Add((NeuralLayerProperties)ctrl);
					}
				}
				return res;
			}
		}

		/// <summary>
		/// Number of ANN inputs.
		/// </summary>
		public int InputsCount
		{
			get { return InputLayer.LayerSize; }
			set { InputLayer.LayerSize = value; }
		}

		/// <summary>
		/// Number of ANN inputs.
		/// </summary>
		public int OutputsCount
		{
			get { return OutputLayer.LayerSize; }
			set
			{
				// set number of nodes for the last layer.
				OutputLayer.LayerSize = value;
			}
		}

		#endregion

		#region - Construction. -

		public NeuralNetProperties()
		{
			InitializeComponent();

			if (InputLayer != null)
			{
				InputLayer.HiddenLayer = false;
				InputLayer.ActivationFunction = ActivationFunctions.Identity;
			}
			if (OutputLayer != null) OutputLayer.HiddenLayer = false;
		}

		#endregion
	}
}
